/* 
  Copyright (c) SilverLining 2015
  Date:    2016-1-7
  File:    BinaryArchiver.cpp  
  Description: 

*/

#include "stdafx.h"

using namespace System;
using namespace System::Security;
using namespace System::Runtime::InteropServices;

#include "shim_object.h"
#include "GameObject.h"
#include "Archiver.h"
#include "BinaryArchiver.h"

using namespace m;
using namespace m::io;

namespace SL
{
	namespace M
	{
		BinaryArchiver::BinaryArchiver()
			: 
			_Buffer(new file_buffer())
		{

		}

		BinaryArchiver::~BinaryArchiver()
		{
			BinaryArchiver::!BinaryArchiver();
		}

		BinaryArchiver::!BinaryArchiver()
		{
			if (_Buffer)
			{
				_Buffer->release();
			}
		}

		array<byte>^ BinaryArchiver::Archive(GameObject ^ root)
		{
			ref_storage track1;
			m::io::binary_serializer* serializer = create(track1, new m::io::binary_serializer());
			Archive(root, serializer);
			_Buffer->clear();
			serializer->save(_Buffer);
			size_t outputSize = _Buffer->size();
			if (outputSize > INT32_MAX)
			{
				throw gcnew IndexOutOfRangeException("Size of data too large.");
			}
			array<byte>^ ret = gcnew array<byte>((int)outputSize);
			pin_ptr<Byte> pRet = &ret[0];

			_Buffer->set_offset(0);
			_Buffer->read((char*)pRet, outputSize);

			return ret;
		}

		void BinaryArchiver::Unarchive(GameObject ^ root, array<byte>^ data)
		{
			if (data == nullptr)
			{
				throw gcnew ArgumentNullException("data");
			}

			pin_ptr<Byte> pData = &data[0];
			_Buffer->clear();
			_Buffer->write((char*)pData, data->Length);

			size_t outputSize = _Buffer->size();
			if (outputSize > INT32_MAX)
			{
				throw gcnew IndexOutOfRangeException("Size of data too large.");
			}

			ref_storage track1;
			m::io::binary_serializer* serializer = create(track1, new m::io::binary_serializer());
			serializer->load(_Buffer);
			Unarchive(root, serializer);
		}
	}
}